package com.lucky.carcodepro.interceptor.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.lucky.carcodepro.common.annotation.RepeatSubmit;
import com.lucky.carcodepro.filter.RepeatedlyRequestWrapper;
import com.lucky.carcodepro.interceptor.RepeatSubmitInterceptor;
import com.lucky.carcodepro.utils.CacheUtils;
import com.lucky.carcodepro.utils.HttpHelper;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * SameUrlDataInterceptor
 * <p>
 * 描述： 判断请求url和数据是否和上一次相同，
 * 如果和上次相同，则是重复提交表单。 有效时间为10秒内。
 *
 * @author Annie
 * @version 2024/10/7 15:49
 */
@Component
public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
{
    public final String REPEAT_PARAMS = "repeatParams";

    public final String REPEAT_TIME = "repeatTime";

    // 令牌自定义标识
    @Value("${token.header}")
    private String header;

    @Override
    public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation)
    {
        var nowParams = StrUtil.EMPTY;
        if (request instanceof RepeatedlyRequestWrapper requestWrapper)
        {
            nowParams = HttpHelper.getBodyString(requestWrapper);
        }
        // body参数为空，获取 Parameter 的数据
        if (StrUtil.isBlankIfStr(nowParams))
        {
            nowParams = JSON.toJSONString(request.getParameterMap());
        }
        Map<String, Object> nowDataMap = new HashMap<>();
        nowDataMap.put(REPEAT_PARAMS, nowParams);
        nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
        // 请求地址作为缓存的 key
        var url = request.getRequestURL().toString();
        // 唯一判断，没有消息头就用请求路由
        var submitKey = StrUtil.trimToEmpty(request.getHeader(header));
        // 唯一标识 key + url + 消息头
        var cacheRepeatKey = url + submitKey;
        Object sessionObject = CacheUtils.get("repeat_submit", cacheRepeatKey);
        if (Objects.isNull(sessionObject))
        {
            Map<String, Object> sessionDataMap = (Map<String, Object>) sessionObject;
            if (sessionDataMap.containsKey(url))
            {
                Map<String, Object> preDataMap = (Map<String, Object>) sessionDataMap.get(url);
                if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval()))
                {
                    return true;
                }
            }
        }
        Map<String, Object> cacheMap = new HashMap<String, Object>();
        cacheMap.put(url, nowDataMap);
        CacheUtils.put("repeat_submit", cacheRepeatKey, cacheMap, annotation.interval(), annotation.timeUnit());

        return false;
    }

    /**
     * 判断参数是否相同
     */
    private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap)
    {
        String nowParams = (String) nowMap.get(REPEAT_PARAMS);
        String preParams = (String) preMap.get(REPEAT_PARAMS);
        return nowParams.equals(preParams);
    }

    /**
     * 判断两次间隔时间
     */
    private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, int interval)
    {
        long time1 = (Long) nowMap.get(REPEAT_TIME);
        long time2 = (Long) preMap.get(REPEAT_TIME);
        if ((time1 - time2) < interval)
        {
            return true;
        }
        return false;
    }
}
